package com.sumer.psychology.blog.domain.model;

import com.sumer.psychology.common.Assert;
import com.sumer.psychology.common.domain.model.Author;
import com.sumer.psychology.common.domain.model.Availability;
import com.sumer.psychology.common.domain.model.ConcurrencySafeEntity;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 博客分类
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/9/3
 * Time: 8:25
 */
public class Category extends ConcurrencySafeEntity {
    private CategoryId categoryId;
    private Author author;
    private String name;
    private Date createTime;
    private Date lastModifyTime;
    private Availability availability;

    Set<Blog> blogs = new HashSet<>(0);

    /**
     * 创建分类
     *
     * @param categoryId id
     * @param author     author
     * @param name       name
     */
    public Category(CategoryId categoryId, Author author, String name) {
        setCategoryId(categoryId);
        setAuthor(author);
        setName(name);
        setCreateTime(new Date());
        setAvailability(Availability.ACTIVE);

        apply(new CategoryCreatedEvent(
                categoryId(),
                author(),
                name()));
    }

    public Category() {
    }

    /**
     * 重命名
     *
     * @param changedName name
     */
    public void changeName(String changedName) {
        setName(changedName);
        setLastModifyTime(new Date());

        apply(new CategoryChangedEvent(
                categoryId(),
                name()));
    }

    /**
     * 删除分类
     */
    public void delete() {
        setAvailability(Availability.DELETED);
        setLastModifyTime(new Date());

        apply(new CategoryDeletedEvent(categoryId()));
    }

    /**
     * 激活状态
     *
     * @return active
     */
    public boolean active() {
        return availability().equals(Availability.ACTIVE);
    }

    private void setCategoryId(CategoryId categoryId) {
        Assert.notNull(categoryId, "id不能为空");
        Assert.notEmpty(categoryId.identity(), "id不能为空");

        this.categoryId = categoryId;
    }

    private void setAuthor(Author author) {
        Assert.notNull(author, "作者不能为空");
        Assert.notEmpty(author.identity(), "作者不能为空");

        this.author = author;
    }

    private void setName(String name) {
        Assert.notEmpty(name, "名称不能为空");
        Assert.length(name, 20, "名称长度不能超过10个字");

        this.name = name;
    }

    private void setCreateTime(Date createTime) {
        Assert.notNull(createTime, "创建时间不能为空");

        this.createTime = createTime;
    }

    private void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    private void setAvailability(Availability availability) {
        Assert.notNull(availability, "状态不能为空");

        this.availability = availability;
    }

    public CategoryId categoryId() {
        return categoryId;
    }

    public Author author() {
        return author;
    }

    public String name() {
        return name;
    }

    public Date createTime() {
        return createTime;
    }

    public Date lastModifyTime() {
        return lastModifyTime;
    }

    public Availability availability() {
        return availability;
    }

    public Set<Blog> blogs() {
        return blogs;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Category category = (Category) o;

        if (author != null ? !author.equals(category.author) : category.author != null) return false;
        if (availability != category.availability) return false;
        if (categoryId != null ? !categoryId.equals(category.categoryId) : category.categoryId != null) return false;
        if (name != null ? !name.equals(category.name) : category.name != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = categoryId != null ? categoryId.hashCode() : 0;
        result = 31 * result + (author != null ? author.hashCode() : 0);
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (availability != null ? availability.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Category{" +
                "categoryId=" + categoryId +
                ", author=" + author +
                ", name='" + name + '\'' +
                ", createTime=" + createTime +
                ", lastModifyTime=" + lastModifyTime +
                ", availability=" + availability +
                '}';
    }

}
